import {
    defineComponent,
    reactive,
    toRefs,
    computed,
    onMounted,
    onBeforeUnmount,
    getCurrentInstance,
    withDirectives,
    nextTick,
    watch,
} from "vue"
import { inject } from "vue"

import { getFixedTotalWidthByColumnKey } from "../util"
import { INSTANCE_METHODS } from "./constant"
import { EMIT_EVENTS, HOOKS_NAME } from "../util/constant"
import { focus } from "amtf/directives"
// import { debounce } from 'lodash'
import { useDebounceFn } from "@vueuse/core"

import { useEmitter } from "amtf/hooks"
import emitter from "amtf/utils/emitter"
import { use样式 } from "amtf/hooks"
import {
    autoResize,
    setCaretPosition,
    getCaretPosition,
    isEmptyValue,
    getValByUnit,
    拼组件名,
    isFunction,
    isBoolean,
    getRandomId,
} from "amtf/utils"
const 主名 = "table-edit-input"
const 组件名 = 拼组件名(主名)

export default defineComponent({
    name: 组件名,
    directives: {
        focus: focus,
    },
    props: {
        parentRendered: {
            type: Boolean,
            required: true,
        },
        hooks: {
            type: Object,
            required: true,
        },
        inputStartValue: {
            type: [String, Number],
            required: true,
        },
        rowKeyFieldName: {
            type: String,
            default: null,
        },
        tableData: {
            type: Array,
            required: true,
        },
        colgroups: {
            type: Array,
            required: true,
        },

        cellSelectionData: {
            type: Object,
            required: true,
        },

        editingCell: {
            type: Object,
            required: true,
        },
        isCellEditing: {
            type: Boolean,
            required: true,
        },
        hasXScrollBar: {
            type: Boolean,
            required: true,
        },
        hasYScrollBar: {
            type: Boolean,
            required: true,
        },
        hasRightFixedColumn: {
            type: Boolean,
            required: true,
        },
        scrollBarWidth: {
            type: Number,
            required: true,
        },
    },
    setup(props, { emit }) {
        // console.log(`编辑 props 👉`, props)
        const instance = getCurrentInstance()
        // console.log(`instance 👉`, instance)

        const { 拼样式名_table直属 } = use样式(主名)
        const a = reactive({
            textareaInputRef: "textareaInputRef",
            rawCellValue: "",
            displayTextarea: false,
            overflowViewport: false,
            textareaRect: { left: 0, top: 0 },
            tableEl: null,
            cellEl: null,
            autoResize: null,
            isEditCellFocus: false,
        })

        const currentColumn = computed(() => {
            // console.log(`currentColumn计算 ing👇`)
            let result = null
            const { colgroups, cellSelectionData } = props
            const { currentCell } = cellSelectionData
            if (!isEmptyValue(currentCell.rowKey) && !isEmptyValue(currentCell.colKey)) {
                result = colgroups.find(x => x.key === currentCell.colKey)
            }
            return result
        })

        const containerClass = computed(() => {
            // console.log(`containerClass ing👇`)
            let result = null
            const { displayTextarea, overflowViewport } = a
            result = {
                [拼样式名_table直属("edit-input-container")]: true,
                [拼样式名_table直属("edit-input-container-show")]: displayTextarea && !overflowViewport,
            }
            return result
        })

        const containerStyle = computed(() => {
            console.log(`containerStyle 计算ing👇`)
            let result = {}
            const { displayTextarea, overflowViewport, textareaRect } = a
            const { top, left } = textareaRect
            // console.log(`displayTextarea 👉`,displayTextarea)
            if (displayTextarea && !overflowViewport) {
                result = {
                    top: top + "px",
                    left: left + "px",
                    height: null,
                    "z-index": currentColumn.value?.fixed ? 10 : 0,
                    opacity: 1,
                }
            } else {
                result = {
                    top: top + "px",
                    left: left + "px",
                    height: "1px",
                    "z-index": -1,
                    opacity: 0,
                }
            }
            return result
        })

        const textareaClass = computed(() => {
            let result = null
            result = {
                [拼样式名_table直属("edit-input")]: true,
            }
            return result
        })

        onMounted(() => {
            a.autoResize = autoResize()
        })

        onBeforeUnmount(() => {
            textareaUnObserve()
        })

        const setTableEl = async () => {
            await nextTick()
            // 获取当前组件根元素的前一个兄弟元素
            a.tableEl = instance.proxy.$el.previousElementSibling
        }

        function setCellEl() {
            console.log(`setCellEl ing👇`)
            const { cellSelectionData } = props
            const { tableEl } = a
            const { rowKey, colKey } = cellSelectionData.currentCell
            if (tableEl) {
                const cellEl = tableEl.querySelector(
                    `tbody.ve-table-body tr[row-key="${rowKey}"] td[col-key="${colKey}"]`
                )
                if (cellEl) {
                    a.cellEl = cellEl
                    a.overflowViewport = false
                }
            }
        }

        function setTextareaPosition() {
            console.log(`setTextareaPosition ing👇`)
            const { cellEl, tableEl } = a
            const { hasXScrollBar, hasYScrollBar, scrollBarWidth, colgroups, hasRightFixedColumn } = props
            if (cellEl && tableEl) {
                const {
                    left: tableLeft,
                    top: tableTop,
                    right: tableRight,
                    bottom: tableBottom,
                } = tableEl.getBoundingClientRect()
                const {
                    left: cellLeft,
                    top: cellTop,
                    height: cellHeight,
                    width: cellWidth,
                    right: cellRight,
                    bottom: cellBottom,
                } = cellEl.getBoundingClientRect()
                if (cellHeight && cellWidth) {
                    let maxHeight = cellHeight + tableBottom - cellBottom
                    let maxWidth = cellWidth + tableRight - cellRight
                    // has horizontal scroll bar
                    if (hasXScrollBar) {
                        maxHeight -= scrollBarWidth
                    }
                    // has vertical scroll bar
                    if (hasYScrollBar) {
                        maxWidth -= scrollBarWidth
                    }
                    // If the right fixed column is included, the max width of the textarea needs to be subtracted from the sum of the right fixed columns
                    if (hasRightFixedColumn) {
                        if (currentColumn.value && !currentColumn.value.fixed) {
                            const rightFixedTotalWidth = getFixedTotalWidthByColumnKey({
                                colgroups,
                                colKey: currentColumn.value.key,
                                fixed: "right",
                            })
                            if (rightFixedTotalWidth) {
                                maxWidth -= rightFixedTotalWidth
                            }
                        }
                    }
                    a.autoResize.init(
                        instance.proxy.$refs[a.textareaInputRef],
                        {
                            minHeight: Math.min(cellHeight, maxHeight),
                            maxHeight: maxHeight,
                            minWidth: Math.min(cellWidth, maxWidth),
                            maxWidth: maxWidth,
                        },
                        true
                    )
                    a.textareaRect = {
                        left: cellLeft - tableLeft,
                        top: cellTop - tableTop,
                    }
                } else {
                    // fixed #477
                    a.textareaRect = {
                        left: 0,
                        top: 0,
                    }
                    a.cellEl = null
                    a.overflowViewport = true
                }
            }
        }

        function showTextarea() {
            setRawCellValue()
            a.displayTextarea = true
        }

        function hideTextarea() {
            a.displayTextarea = false
            textareaUnObserve()
        }

        function textareaUnObserve() {
            if (a.autoResize) {
                a.autoResize.unObserve()
            }
        }

        function setRawCellValue() {
            a.rawCellValue = props.inputStartValue
        }

        function textareaValueChange(val) {
            emit(EMIT_EVENTS.EDIT_INPUT_VALUE_CHANGE, val)
        }

        function textareaSelect() {
            const textareaInputEl = instance.proxy.$refs[a.textareaInputRef]
            if (textareaInputEl) {
                textareaInputEl.select()
            }
        }

        function textareaAddNewLine() {
            const { isCellEditing, editingCell } = props
            if (isCellEditing) {
                const textareaInputEl = instance.proxy.$refs[a.textareaInputRef]
                const caretPosition = getCaretPosition(textareaInputEl)
                let value = editingCell.row[editingCell.colKey]
                // solve error of number slice method
                value += ""
                const newValue = `${value.slice(0, caretPosition)}\n${value.slice(caretPosition)}`
                // 直接更新 textarea 值
                textareaInputEl.value = newValue
                // 手动赋值不会触发textarea 文本变化事件,需要手动更新 editingCell 值
                textareaValueChange(newValue)
                setCaretPosition(textareaInputEl, caretPosition + 1)
            }
        }

        const debounceSetTextareaPosition = useDebounceFn(setTextareaPosition, 210)

        const debounceSetCellEl = useDebounceFn(() => {
            if (a.displayTextarea) {
                if (!a.cellEl) {
                    setCellEl()
                }
            }
        }, 200)

        watch(
            () => props.parentRendered,
            val => {
                // console.log(`props.parentRendered变化了 👉`, val)
                if (val) {
                    // fixed #471
                    setTableEl()
                    // add table container scroll hook
                    props.hooks.addHook(HOOKS_NAME.TABLE_CONTAINER_SCROLL, () => {
                        if (a.displayTextarea) {
                            if (!a.cellEl) {
                                setCellEl()
                            }
                        }
                        debounceSetCellEl()
                        setTextareaPosition()
                        debounceSetTextareaPosition()
                    })
                    // add table size change hook
                    props.hooks.addHook(HOOKS_NAME.TABLE_SIZE_CHANGE, () => {
                        setTextareaPosition()
                    })
                }
            },
            { immediate: true, deep: true }
        )

        watch(
            () => props.isCellEditing,
            (newVal, oldVal) => {
                // console.log('props.isCellEditing 变化 ing👇')
                if (newVal) {
                    showTextarea()
                } else {
                    hideTextarea()
                }
            },
            { immediate: true, deep: true }
        )

        watch(
            () => props.cellSelectionData?.currentCell,
            val => {
                a.isEditCellFocus = false
                const { rowKey, colKey } = val || {}
                if (!isEmptyValue(rowKey) && !isEmptyValue(colKey)) {
                    setCellEl()
                    // wait for selection cell rendered
                    nextTick(() => {
                        setTextareaPosition()
                        setTimeout(() => {
                            a.isEditCellFocus = true
                        })
                    })
                }
            },
            { deep: true, immediate: true }
        )

        // 监听 cellSelectionData.normalEndCell
        watch(
            () => props.cellSelectionData?.normalEndCell,
            val => {
                /*
                trigger editor(textarea) element select
                解决通过点击的区域选择，无法复制的问题
                */
                if (!isEmptyValue(val?.colKey)) {
                    textareaSelect()
                }
            },
            { deep: true, immediate: true }
        )

        // 监听 inputStartValue
        watch(
            () => props.inputStartValue,
            () => {
                setRawCellValue()
            },
            { immediate: true }
        )

        return () => {
            const focusDirective = withDirectives(
                <textarea
                    ref={a.textareaInputRef}
                    class={textareaClass.value}
                    value={a.rawCellValue}
                    tabindex={-1}
                    onInput={e => {
                        if (props.isCellEditing) {
                            textareaValueChange(e.target.value)
                            a.rawCellValue = e.target.value
                        }
                    }}
                    onClick={() => emit(EMIT_EVENTS.EDIT_INPUT_CLICK)}
                    onCopy={e => emit(EMIT_EVENTS.EDIT_INPUT_COPY, e)}
                    onPaste={e => emit(EMIT_EVENTS.EDIT_INPUT_PASTE, e)}
                    onCut={e => emit(EMIT_EVENTS.EDIT_INPUT_CUT, e)}
                />,
                [[focus, { 是focus否: a.isEditCellFocus }]] // 指令参数
            )

            return (
                <div style={containerStyle.value} class={containerClass.value}>
                    {focusDirective}
                </div>
            )
        }

        // return () =>
        //   withDirectives(
        //     <div style={containerStyle.value} class={containerClass.value}>
        //       <textarea
        //         ref={a.textareaInputRef}
        //         class={textareaClass.value}

        //         value={a.rawCellValue}
        //         tabindex="-1"
        //         onInput={(e) => {
        //           if (props.isCellEditing) {
        //             textareaValueChange(e.target.value)
        //             a.rawCellValue = e.target.value
        //           }
        //         }}
        //         onClick={() => emitter.on(EMIT_EVENTS.EDIT_INPUT_CLICK)}
        //         onCopy={(e) => emitter.on(EMIT_EVENTS.EDIT_INPUT_COPY, e)}
        //         onPaste={(e) => emitter.on(EMIT_EVENTS.EDIT_INPUT_PASTE, e)}
        //         onCut={(e) => emitter.on(EMIT_EVENTS.EDIT_INPUT_CUT, e)}
        //       />
        //     </div>
        //   )
    },
})
